;; =============
;; EXERCISE 2.04
;; =============

;; Here is an alternative procedural representation of pairs. For this
;; representation, verify that (car (cons x y)) yields x for any
;; objects x and y.

(define (cons x y)
  (lambda (m) (m x y)))

(define (car z)
  (z (lambda (p q) p)))

;; What is the corresponding definition of cdr? (Hint: To verify that
;; this works, make use of the substitution model of Section 1.1.5.)

;; =============
;; SOLUTION 2.04
;; =============

;; `car` and `cdr` will expect whatever `cons` returns. `cons` returns
;; a procedure, which takes one argument applies it to the parts of
;; the pair `x` and `y`, which are in its environment. Thus, if we
;; give the procedure returned by `cons` a procedure, which returns
;; the first or the second of the arguments it receives, we get the
;; first or second part of the pair respectively.
(define (cdr z)
  (z (lambda (p q) q)))

;; `car` and `cdr` are masking the fact, that `cons` returns a
;; procedure. It is irrelevant, if we only ever interact with pairs
;; using `cons`, `car` and `cdr`.

;; =====
;; TESTS
;; =====
(use-modules (srfi srfi-64))

(test-begin "test-cons-car-cdr")
(test-group
 "test-cons-car-cdr"
 (test-equal
     (car (cons 5 4)) 5)
 (test-equal
     (cdr (cons 5 4)) 4))

(test-end "test-cons-car-cdr")
